package com.scalesoft.artsync.modelimpl.submission.artwork;

import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

import com.scalesoft.artsync.model.submission.artwork.ArtworkSubmission;
import com.scalesoft.artsync.modelimpl.submission.SubmissionImpl;

public class ArtworkSubmissionImpl extends SubmissionImpl implements ArtworkSubmission {

	private final int THUMBNAIL_WIDTH = 100;
	private final int THUMBNAIL_HEIGHT = 100;
	private String filename;
	private int width;
	private int height;

	@Override
	public ImageIcon getIcon() {
		Image icon = loadThumbnail(filename);
		if (icon != null)
			return new ImageIcon(icon);

		return null;
	}

	@Override
	public String getFilename() {
		return filename;
	}

	@Override
	public void setFilename(String filename) {
		this.filename = filename;
	}

	// Image functions ----------------------------------

	private Image loadThumbnail(String filename) {
		// No thumbnail yet? Then create it.
		File f = new File("files/thumbnails/" + filename);
		if (!f.exists() || f.length() == 0) {
			f = new File("files/" + filename);
			if (f.exists() && f.length() > 0) {
				processImage(filename);
			} else {
				return null;
				// filename = "nothumb.jpg";
			}
		}
		try {
			return ImageIO.read(new File("files/thumbnails/" + filename));
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		return null;
	}

	// Create thumbnails and preview images from original
	private void processImage(String filename) {
		Image image = null;
		try {
			File f = new File("files/" + filename);
			System.out.println("Processing thumbnail: " + f.getAbsolutePath());
			image = ImageIO.read(f);
			// image = Toolkit.getDefaultToolkit().createImage(filename);
			MediaTracker mediaTracker = new MediaTracker(new Container());
			mediaTracker.addImage(image, 0);
			mediaTracker.waitForID(0);
			mediaTracker = null;
		} catch (Exception e1) {
			e1.printStackTrace();
			return;
		}
		// Small thumbnail
		this.width = image.getWidth(null);
		this.height = image.getHeight(null);
		Dimension d = getScaledDimension(image.getWidth(null), image.getHeight(null), THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
		System.out.println("Rescaled size: " + d.getWidth() + "/" + d.getHeight());
		BufferedImage rescaled = getScaledInstance(image, (int) d.getWidth(), (int) d.getHeight());
		saveJPG(rescaled, "files/thumbnails/" + filename);
		image = null;
		rescaled = null;
	}

	public static Dimension getScaledDimension(int ow, int oh, int tw, int th) {
		float widthratio = (float) ow / (float) tw;
		float heightratio = (float) oh / (float) th;
		if (widthratio > heightratio) {
			tw = (int) ((float) ow / widthratio);
			th = (int) ((float) oh / widthratio);
		} else {
			tw = (int) ((float) ow / heightratio);
			th = (int) ((float) oh / heightratio);
		}
		return new Dimension(tw, th);
	}

	private BufferedImage getScaledInstance(Image original, int targetWidth, int targetHeight) {
		int type = BufferedImage.TYPE_INT_RGB;
		BufferedImage img = imageToBufferedImage(original);
		BufferedImage ret = (BufferedImage) img;
		int w, h;
		boolean higherQuality = true;

		if (original.getWidth(null) < targetWidth || original.getHeight(null) < targetHeight)
			higherQuality = false;

		if (higherQuality) {
			// Use multi-step technique: start with original size, then
			// scale down in multiple passes with drawImage()
			// until the target size is reached
			w = img.getWidth();
			h = img.getHeight();
		} else {
			// Use one-step technique: scale directly from original
			// size to target size with a single drawImage() call
			w = targetWidth;
			h = targetHeight;
		}

		do {
			if (higherQuality && w > targetWidth) {
				w /= 2;
				if (w < targetWidth) {
					w = targetWidth;
				}
			}
			if (higherQuality && h > targetHeight) {
				h /= 2;
				if (h < targetHeight) {
					h = targetHeight;
				}
			}
			BufferedImage tmp = new BufferedImage(w, h, type);
			Graphics2D g2 = tmp.createGraphics();
			g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
			g2.drawImage(ret, 0, 0, w, h, null);
			g2.dispose();
			ret = tmp;
		} while (w != targetWidth || h != targetHeight);
		return ret;
	}

	private void saveJPG(BufferedImage image, String filename) {
		try {
			ImageIO.write(image, "jpg", new File(filename));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private BufferedImage imageToBufferedImage(Image source) {
		BufferedImage target = new BufferedImage(source.getWidth(null), source.getHeight(null),
				BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = target.createGraphics();
		g2.drawImage(source, 0, 0, (int) source.getWidth(null), (int) source.getHeight(null), null);
		g2.dispose();
		return target;
	}

	@Override
	public int getHeight() {
		return height;
	}

	@Override
	public int getWidth() {
		return width;
	}

}
